﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Core.Model;
using DapperExtensions;
using DapperExtensions.Mapper;
using log4net;

namespace DataServer.Dao
{
    public class DeviceDao : BaseDao<Device>
    {
        private readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static DeviceMapper _deviceMapper;

        public DeviceDao()
        {
            if (_deviceMapper == null)
            {
                _deviceMapper = new DeviceMapper();
            }
        }

        protected override string GetTableName()
        {
            if (_deviceMapper != null)
                return _deviceMapper.TableName;
            return "device";
        }

        public Device GetEntityById(string id)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Device>(f => f.Id, Operator.Eq, id);
                IList<ISort> sort = new List<ISort>();
                sort.Add(new Sort { PropertyName = "Position", Ascending = true });
                Device Device = result?.Connection.Get<Device>(predicate, sort);
                return Device;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public Device GetEntityByName(string name)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Device>(f => f.Name, Operator.Eq, name);
                Device Device = result?.Connection.Get<Device>(predicate);
                return Device;
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }
        public List<Device> GetDevicesByIds(string devIds)
        {
            if(devIds == null || devIds.Length==0)
                return null;
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                string sql = $"SELECT * FROM {_deviceMapper.TableName} WHERE Id IN({devIds})";
                IEnumerable<Device> devices = result?.Connection.GetList<Device>(sql);
                return devices?.ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }
        public List<Device> GetDevicesByChlId(string chlId)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Device>(f => f.ChannelId, Operator.Eq, chlId);
                IList<ISort> sort = new List<ISort>();
                sort.Add(new Sort { PropertyName = "Position", Ascending = true });
                IEnumerable<Device> devices = result?.Connection.GetList<Device>(predicate, sort);
                return devices?.ToList();
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return null;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

        public bool DeleteDevicesByChlId(string chlId)
        {
            ConnectResult result = null;
            try
            {
                result = OpenDbConnection();
                var predicate = Predicates.Field<Device>(f => f.ChannelId, Operator.Eq, chlId);
                return result.Connection.Delete<Device>(predicate);
            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                return false;
            }
            finally
            {
                if (result != null)
                {
                    CloseDbConnection(result.Name);
                }
            }
        }

    }
    public sealed class DeviceMapper : ClassMapper<Device>
    {
        public DeviceMapper()
        {
            Table("device");
            Map(x => x.Id).Key(KeyType.Assigned);
            Map(x => x.DeviceType).Ignore();
            Map(x => x.IsConnected).Ignore();
            Map(x => x.BreakCount).Ignore();
            //Ignore this property entirely
            //optional, map all other columns
            AutoMap();
        }
    }
}
